package com.tulink.yichutu.biz;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Joiner;
import com.tulink.yichutu.entity.WxVipCashCouponEntity;
import com.tulink.yichutu.entity.WxVipGoodsEntity;
import com.tulink.yichutu.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 兑换码业务方法
 *
 * @author wanchaopeng
 */
@Slf4j
@Component
public class CashCouponBiz {
    private static final String cashCouponCacheKey = "cashCoupons";

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxVipCashCouponService wxVipCashCouponService;
    @Autowired
    private OrderBiz orderBiz;

    public WxVipCashCouponEntity getCashCoupon(String code) {
        try {
            Object obj = redisTemplate.boundHashOps(cashCouponCacheKey).get(code);
            if(obj == null) {
                return null;
            }
            return JSON.parseObject(obj.toString(), WxVipCashCouponEntity.class);
        } catch (Exception ex) {
            log.error("getCashCoupon error", ex);
        }
        return null;
    }

    public List<WxVipCashCouponEntity> getByCodes(String... codes) {
        if(codes == null || codes.length < 1) {
            return new ArrayList<>();
        }
        return wxVipCashCouponService.list(
                Wrappers.<WxVipCashCouponEntity>lambdaQuery()
                        .eq(WxVipCashCouponEntity::getCode, codes)
        );
    }

    public boolean useCoupon(WxVipCashCouponEntity cashCouponEntity) {
        return wxVipCashCouponService.update(
                Wrappers.<WxVipCashCouponEntity>lambdaUpdate()
                        .set(WxVipCashCouponEntity::getStatus, 1)
                        .eq(WxVipCashCouponEntity::getId, cashCouponEntity.getId())
                        .eq(WxVipCashCouponEntity::getStatus, 0)
        );
    }

    public boolean hasName(String name) {
        if(StringUtils.isBlank(name)) {
            return false;
        }
        return wxVipCashCouponService.count(
                Wrappers.<WxVipCashCouponEntity>lambdaQuery()
                        .eq(WxVipCashCouponEntity::getName, name.trim())
        ) > 0;
    }

    public List<WxVipCashCouponEntity> getByName(String name) {
        if(StringUtils.isBlank(name)) {
            return new ArrayList<>();
        }
        return wxVipCashCouponService.list(
                Wrappers.<WxVipCashCouponEntity>lambdaQuery()
                        .eq(WxVipCashCouponEntity::getName, name.trim())
        );
    }

    public List<WxVipCashCouponEntity> generatorCode(String name, Integer count, WxVipGoodsEntity goodsEntity) {
        if(count == null || count < 1) {
            return new ArrayList<>();
        }
        List<WxVipCashCouponEntity> cashCouponEntities = new ArrayList<>();
        for(int i = 0; i < count; i++) {
            WxVipCashCouponEntity cashCouponEntity = new WxVipCashCouponEntity();
            cashCouponEntity.setCode("CC-" + UUID.randomUUID().toString().toUpperCase().replace("-", ""));
            cashCouponEntity.setCodePrice(goodsEntity.getPrice());
            cashCouponEntity.setGoodsCount(1);
            cashCouponEntity.setGoodsId(goodsEntity.getId());
            cashCouponEntity.setName(name);
            cashCouponEntity.setStatus(0);
            cashCouponEntities.add(cashCouponEntity);
        }
        wxVipCashCouponService.saveBatch(cashCouponEntities);
        putCache(cashCouponEntities);
        return cashCouponEntities;
    }

    public void removeCache(String... codes) {
        if(codes == null || codes.length < 1) {
            return;
        }
        try {
            log.info("移除兑换码缓存：{}", Joiner.on(",").join(codes));
            redisTemplate.boundHashOps(cashCouponCacheKey).delete(codes);
        } catch (Exception ex) {
            log.error("removeCache error：" + Joiner.on(",").join(codes), ex);
        }
    }

    public void delete(String... codes) {
        if(codes == null || codes.length < 1) {
            return;
        }
        log.info("删除兑换码：{}", Joiner.on(",").join(codes));
        wxVipCashCouponService.remove(
                Wrappers.<WxVipCashCouponEntity>lambdaQuery()
                        .in(WxVipCashCouponEntity::getCode, codes)
        );
        removeCache(codes);
    }

    @PostConstruct
    public void initCache() {
        int count = 0;
        int total = 0;
        log.info("开始初始化缓存...");
        int pageSize = 500;
        redisTemplate.delete(cashCouponCacheKey);
        while(count < 10000) {
            Page<WxVipCashCouponEntity> page = new Page<>(count, pageSize);
            page = wxVipCashCouponService.page(
                    page,
                    Wrappers.<WxVipCashCouponEntity>lambdaQuery().eq(WxVipCashCouponEntity::getStatus, 0)
            );
            putCache(page.getRecords());
            Map<String, String> cashCouponEntityMap = page.getRecords()
                    .stream()
                    .collect(Collectors.toMap(WxVipCashCouponEntity::getCode, p -> JSONObject.toJSONString(p), (p1, p2) -> JSONObject.toJSONString(p2)));
            total += cashCouponEntityMap.size();
            log.info("兑换码已加载：{}", total);
            if(page.getRecords().size() < pageSize) {
                break;
            }
            count++;
        }
        log.info("初始化兑换码缓存完成：{}", total);
    }

    private void putCache(List<WxVipCashCouponEntity> cashCouponEntities) {
        Map<String, String> cashCouponEntityMap = cashCouponEntities
                .stream()
                .collect(Collectors.toMap(WxVipCashCouponEntity::getCode, p -> JSONObject.toJSONString(p), (p1, p2) -> JSONObject.toJSONString(p2)));
        if(cashCouponEntityMap.size() > 0) {
            redisTemplate.boundHashOps(cashCouponCacheKey).putAll(cashCouponEntityMap);
        }
    }
}
